//
//  SessionViewController.m
//  网络
//
//  Created by hfzhangzhang on 2018/4/11.
//  Copyright © 2018年 hfzhangzhang. All rights reserved.
//

#import "SessionViewController.h"

@interface SessionViewController ()<NSURLSessionDownloadDelegate>
/** 全局的网络会话(Session),管理所有的网络任务  */
@property(nonatomic,strong)NSURLSession * session;
/** 续传的数据  */
@property(nonatomic,strong)NSData * resumeData;
/** 全局的下载任务  */
@property(nonatomic,strong)NSURLSessionDownloadTask * downloadTask;
@end

@implementation SessionViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

-(NSURLSession *)session
{
    if (_session == nil) {
        //config 提供了一个全局的网络环境配置,包括:身份验证,浏览器类型,cookie,缓存,超时...
        NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        /*
         队列: 设置回调的代理方法在哪里执行!!
         - 代理的队列 如果给 nil 哥么在 多个线程执行
         - [NSOperationQueue mainQueue] 主队列
         */
        /*
         The session object keeps a strong reference to the delegate
         Session 会对代理进行强引用!!如果任务执行结束后,不取消session,会出现内存泄露!!
         
         
         真正的网络访问!
         - 在网络开发中,应该讲所有的网络访问操作,封装到一个方法中,由一个统一的单例对象来负责素有的网络事件!
         - Session对代理(单例)进行强引用!单例本身就是一个静态的实例,本身就不需要释放!!
         - AFN -> 需要建立一个AFN 的Manager
         */
        
        _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
    }
    return _session;
}
-(void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    //取消会话
    [self.session invalidateAndCancel];
    self.session = nil;
}
- (IBAction)start {
    NSURL * url = [NSURL URLWithString:@"http://sw.bos.baidu.com/sw-search-sp/software/50045684f7da6/QQ_mac_5.4.1.dmg"];
    NSLog(@"开始");
    self.downloadTask = [self.session downloadTaskWithURL:url];
    [self.downloadTask resume];
    NSLog(@"%@",[NSThread currentThread]);
}

//暂停
- (IBAction)pause:(id)sender {
    NSLog(@"暂停");
    [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
        //resumeData : 续传的数据(下载了多少)
        NSLog(@"数据的长度是: %tu",resumeData.length);
        self.resumeData = resumeData;
        
        //释放下载任务
        // - 让我们tast设置为week 就可以不用释放了!
        // - 因为任务都是由Session发起的!!而Session对发起的任务都会持有一个强引用!
        self.downloadTask = nil;
    }];
}


//继续
- (IBAction)resume:(id)sender {
    if (self.resumeData == nil) {
        NSLog(@"哥么没有暂停的任务");
        return;
    }
    //所有任务都是由session发起的!
    //使用续传数据启动下载任务
    self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    //清空续传数据
    self.resumeData = nil;
    
    //所有的任务都是默认挂起的!!
    [self.downloadTask resume];
}


#pragma mark - <NSURLSessionDownloadDelegate>
/**
 iOS 7.0 ,一下三个方法都是必须实现的!! 到了 iOS 8.0 只剩下下载完成是必须的!!
 
 */


//1. 下载完成方法
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
    NSLog(@"完成 %@",location);
}


//2.下载进度
/**
 1.session
 2.downloadTask                 调用代理方式的的下载任务!
 3.bytesWritten                 本次下载的字节数!
 4,totalBytesWritten            已经下载的字节数!
 5,totalBytesExpectedToWrite    期望下载的字节数-->文件总大小!
 */
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    float progress = (float) totalBytesWritten / totalBytesExpectedToWrite;
    NSLog(@"%f %@",progress,[NSThread currentThread]);
    //回到主线程更新UI
    dispatch_async(dispatch_get_main_queue(), ^{

    });
}


//3.下载续传数据
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
    
}




- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}













































-(void)seesionDemo1{
    //1.url
    NSURL * url = [NSURL URLWithString:@"http://192.168.31.180/videos.json"];
    
    //2.NSURLSession  -> 苹果提供了一个全局的单例,简化我们的开发
    NSURLSession * session = [NSURLSession sharedSession];
    
    //3.NSURLSessionDataTask -> 在NSURLSession 开发中,所有的任务都是由Session发起的!!
    
    /**
     如果使用Block 回调 ,默认哥么是异步的
     所以如果要更新UI ,需要"线程间通讯"
     */
    
    NSURLSessionDataTask * task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        //反序列化
        id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"%@",result);
    }];
    
    //4.启动任务
    [task resume];
    
    
//    NSURL * url = [NSURL URLWithString:@"http://192.168.31.180/sszip.zip"];
//
//    /*
//     如果在回调方法中,不做任何处理,下载的文件会被删除
//     下载文件放在temp里面的!系统会自动回收这块区域!
//
//
//     设计的目的是什么?
//     - 通常从网络上下载文件,什么格式文件最多 -> zip 文件最多!可以替用户节约流量!
//     - 如果是 zip 包,下载之后,需要解压
//     - 解压缩之后,原始的 zip 文件就不在需要了.系统会自动帮我们删除!
//
//     */
//    [[[NSURLSession sharedSession] downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//
//        NSLog(@"%@",location);
//        //下载结束,解压缩到目标路径
//        NSString * cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
//        /** 只需要知道目标路径,不需要知道目标文件 */
//        // 因为一个压缩包中有可能有多个文件
//        [SSZipArchive unzipFileAtPath:location.path toDestination:cachePath];
//
//    }] resume];
}


@end
